timer = {
    _div: 0,
    _tima: 0,
    _tma: 0,
    _tac: 0,

    _clock: { main: 0, sub: 0, div: 0 },
    /*
    init: function () {
        timer._div = 0xaf;
        timer._tima = 0;
        timer._tma = 0;
        timer._tac = 0xf8;
    },*/

    reset: function () {
        timer._div = 0;
        timer._sdiv = 0;
        timer._tma = 0;
        timer._tima = 0;
        timer._tac = 0;
        timer._clock.main = 0;
        timer._clock.sub = 0;
        timer._clock.div = 0;
    },

    step: function () {
        timer._tima++;
        timer._clock.main = 0;
        if (timer._tima > 255) {
            timer._tima = timer._tma;
            mmu._if |= 4;
        }
    },

    run: function () {
        var oldclk = timer._clock.main;
        timer._clock.sub += cpu._r.t / 4;
        if (timer._clock.sub > 3) {
            timer._clock.main++;
            timer._clock.sub -= 4;

            timer._clock.div++;
            if (timer._clock.div == 16) {
                timer._clock.div = 0;
                timer._div++;
                timer._div &= 255;
            }
        }

        if (timer._tac & 4) {
            switch (timer._tac & 3) {
                case 0:
                    if (timer._clock.main >= 64) timer.step();
                    break;
                case 1:
                    if (timer._clock.main >= 1) timer.step();
                    break;
                case 2:
                    if (timer._clock.main >= 4) timer.step();
                    break;
                case 3:
                    if (timer._clock.main >= 16) timer.step();
                    break;
            }
        }
    },

    rb: function (addr) {
        switch (addr) {
            case 0xff04: return timer._div;
            case 0xFF05: return timer._tima;
            case 0xFF06: return timer._tma;
            case 0xFF07: return timer._tac;
        }
    },
    wb: function (addr, val) {
        switch (addr) {
            case 0xFF04: timer._div = 0; break;
            case 0xFF05: timer._tima = val; break;
            case 0xFF06: timer._tma = val; break;
            case 0xFF07: timer._tac = val & 7; break;
        }
    }
}